package com.gitee.wsl.math.vector

import com.gitee.wsl.ext.collection.maxValueIndex
import kotlin.math.sqrt

class ListVector(val values: List<Double>):Vector,List<Double> by values {
    /**
     * Creates a new 2d vector.
     */
    constructor(x: Float, y: Float) : this(listOf(x.toDouble(), y.toDouble()))

    override val argmax: Int get() =  values.maxValueIndex()

    override val numActives: Int get() = size

    override val numNonzeros: Int
      get() {
        var nnz = 0
        values.forEach { v ->
            if (v != 0.0) {
                nnz += 1
            }
        }
        return nnz
    }

    override fun toSparseWithSize(nnz: Int): SparseVector {
        TODO("Not yet implemented")
    }

    override fun toArray(): DoubleArray {
        TODO("Not yet implemented")
    }

    override fun copy(): SparseVector {
        TODO("Not yet implemented")
    }

    override fun set(index: Int, value: Double) {
        TODO("Not yet implemented")
    }

    override fun foreachActive(f: (Int, Double) -> Unit) {
        TODO("Not yet implemented")
    }

    // vector * scalar
     override operator fun times(scalar: Float): Vector = ListVector(values.map { it * scalar })

     override operator fun div(f: Float): Vector {
        return times(1 / f)
    }

    /**
     * Dot product of 2 vectors.
     */
     override operator fun times(vector: Vector): Double {
        require(values.size == vector.size) { "Dot product requires that both vectors are the same length" }

        return values.foldIndexed(0.0) { index, acc, t ->
            acc + t * vector[index]
        }
    }

     override operator fun plus(vector: Vector): Vector {
        require(values.size == vector.size) { "Addition requires that both vectors are the same length" }

        return ListVector(
            values.mapIndexed { index, i ->
                i + vector[index]
            }
        )
    }

     override operator fun minus(vector: Vector): Vector {
        require(values.size == vector.size) { "Subtraction requires that both vectors are the same length" }
        return ListVector(
            values.mapIndexed { index, i ->
                i - vector[index]
            }
        )
    }

     override fun norm(): Double {
        return sqrt(
            values.fold(0.0) { acc, fl ->
                acc + fl * fl
            }
        )
    }

}